// file:src/kernel/syscall.c
// autour:jiangxinpeng
// time:2021.2.25
// upate: 2022.1.9
// copyright:(C) by jiangxinepgn,All right are reserved.

#include <os/syscall.h>
#include <os/exception.h>
#include <os/walltime.h>
#include <os/task.h>
#include <os/timer.h>
#include <os/sleep.h>
#include <os/alarm.h>
#include <os/clock.h>
#include <os/debug.h>
#include <os/kernel.h>
#include <os/msgqueue.h>
#include <os/share.h>
#include <os/pthread.h>
#include <os/config.h>
#include <os/syscall.h>
#include <os/process.h>
#include <os/account_group.h>
#include <os/exec.h>
#include <os/account.h>
#include <os/schedule.h>
#include <os/sem.h>
#include <os/pipe.h>
#include <os/environ.h>
#include <os/driver.h>
#include <os/diskman.h>
#include <os/swap.h>
#include <os/kernel.h>
#include <os/fs.h>
#include <os/fifo.h>
#include <os/log.h>
#include <os/environ.h>
#include <sys/select.h>
#include <sys/swap.h>
#include <arch/interrupt.h>
#include <arch/power.h>
#include <os/sockcall.h>

#pragma GCC optimize("O0")

// global syscall number
syscall_t syscalls[SYSCALL_NUM_MAX];

// syscall function interface
void SysCallInit()
{
    int i;

    for (i = 0; i < SYSCALL_NUM_MAX; i++)
    {
        syscalls[i] = SysCallDefault;
    }
#if CONFIG_NET
    syscalls[SYS_SOCKETCALL] = SysSockcall;
#endif
    syscalls[SYS_DEBUG]=SysDebug;
    syscalls[SYS_GETPID] = SysGetPid;
    syscalls[SYS_WAITPID] = SysWaitPid;
    syscalls[SYS_FORK] = SysFork;
    syscalls[SYS_SLEEP] = SysSleep;
    syscalls[SYS_GETPPID] = SysGetParPid;
    syscalls[SYS_GETTID] = SysGetThreadPid;
    syscalls[SYS_GETPGID] = SysGetProcessGroupId;
    syscalls[SYS_SETPGID] = SysSetProcessGroupId;
    syscalls[SYS_TSTATUS] = SysTaskStatus;
    syscalls[SYS_SCANDEV] = SysScanDev;
    syscalls[SYS_HEAP] = SysMemSpaceExpandHeap;
    syscalls[SYS_THREAD_CREATE] = SysThreadCreate;
    syscalls[SYS_THREAD_EXIT] = SysThreadExit;
    syscalls[SYS_THREAD_CANNEL] = SysThreadCancel;
    syscalls[SYS_THREAD_JOIN] = SysThreadJoin;
    syscalls[SYS_THREAD_DETACH] = SysThreadDetach;
    syscalls[SYS_THREAD_CANCELSTATUS] = SysThreadSetCancelStatus;
    syscalls[SYS_THREAD_CANCELTYPE] = SysThreadSetCancelType;
    syscalls[SYS_THREAD_TESTCANCEL] = SysThreadTestCancel;
    syscalls[SYS_USLEEP] = SysUSleep;
    syscalls[SYS_ALARM] = SysAlarm;
    syscalls[SYS_TIMES] = SysTime;
    syscalls[SYS_EXECVE] = SysExec;
    syscalls[SYS_GETTIMEOFDAY] = SysGetTimeOfDay;
    syscalls[SYS_GETTICKS] = SysGetTicks;
    syscalls[SYS_GETWALLTIME] = SysGetWallTime;
    syscalls[SYS_CLOCK_GETTIME] = SysClockGetTime;
    syscalls[SYS_GETHOSTNAME] = SysGetHostName;
    syscalls[SYS_CONFIG] = SysConfig;
    syscalls[SYS_MSGQUEUEGET] = SysMsgQueueGet;
    syscalls[SYS_MSGQUEUEPUT] = SysMsgQueuePut;
    syscalls[SYS_MSGQUEUERECV] = SysMsgQueueRecv;
    syscalls[SYS_MSGQUEUESEND] = SysMsgQueueSend;
    syscalls[SYS_SHAREMEMDOWN] = SysShareMemDown;
    syscalls[SYS_SHAREMEMUP] = SysShareMemUp;
    syscalls[SYS_SHAREMEMGET] = SysShareMemGet;
    syscalls[SYS_SHAREMEMPUT] = SysShareMemPut;
    syscalls[SYS_SHAREMEMMAP] = SysShareMemMap;
    syscalls[SYS_SHAREMEMUNMAP] = SysShareMemUnmap;
    syscalls[SYS_SEMGET] = SysSemGet;
    syscalls[SYS_SEMPUT] = SysSemPut;
    syscalls[SYS_SEMDOWN] = SysSemDown;
    syscalls[SYS_SEMUP] = SysSemUp;
    syscalls[SYS_LOGWRITE] = SysLogWrite;
    syscalls[SYS_LOGREAD] = SysLogRead;
    syscalls[SYS_LOGDEL] = SysLogDel;
    syscalls[SYS_LOGFIND] = SysLogFind;
    syscalls[SYS_EXIT] = SysExit;
    syscalls[SYS_REBOOT] = SysReboot;
    syscalls[SYS_POWEROFF] = SysPowerOff;
    syscalls[SYS_SELECT] = SysSelect;
    syscalls[SYS_READ] = SysRead;
    syscalls[SYS_WRITE] = SysWrite;
    syscalls[SYS_OPEN] = SysOpen;
    syscalls[SYS_CLOSE] = SysClose;
    syscalls[SYS_IOCTL] = SysIoCtl;
    syscalls[SYS_FCNTL] = SysFcntl;
    syscalls[SYS_FTRUNCATE] = SysFtruncate;
    syscalls[SYS_UNLINK] = SysUnlink;
    syscalls[SYS_DUP] = SysDup;
    syscalls[SYS_DUP2] = SysDup2;
    syscalls[SYS_OPENDIR] = SysOpenDir;
    syscalls[SYS_PIPE] = SysPipe;
    syscalls[SYS_CLOSEDIR] = SysCloseDir;
    syscalls[SYS_READDIR] = SysReadDir;
    syscalls[SYS_REWIND] = SysRewind;
    syscalls[SYS_CHDIR] = SysChDir;
    syscalls[SYS_MKDIR] = SysMkDir;
    syscalls[SYS_RMDIR] = SysRmDir;
    syscalls[SYS_GETCWD] = SysGetCwd;
    syscalls[SYS_FSTATUS] = SysFStatus;
    syscalls[SYS_STATUS] = SysStatus;
    syscalls[SYS_TELL] = SysTell;
    syscalls[SYS_REWINDDIR] = SysRewindDir;
    syscalls[SYS_ACCESS] = SysAccess;
    syscalls[SYS_MKFS] = SysMkfs;
    syscalls[SYS_MOUNT] = SysMount;
    syscalls[SYS_UNMOUNT] = SysUnMount;
    syscalls[SYS_CHMOD] = SysChmod;
    syscalls[SYS_RENAME] = SysRename;
    syscalls[SYS_LSEEK] = SysLSeek;
    syscalls[SYS_FASTIO] = SysFastIo;
    syscalls[SYS_FASTREAD] = SysFastRead;
    syscalls[SYS_FASTWRITE] = SysFastWrite;
    syscalls[SYS_MMAP] = SysMmap;
    syscalls[SYS_CREATEPROCESS] = SysCreateProcess;
    syscalls[SYS_RESUMEPROCESS] = SysResumeProcess;
    syscalls[SYS_BIND_PORT] = SysPortComBind;
    syscalls[SYS_UNBIND_PORT] = SysPortComUnBind;
    syscalls[SYS_RECEIVE_PORT] = SysPortComReceive;
    syscalls[SYS_REPLY_PORT] = SysPortComReply;
    syscalls[SYS_REQUEST_PORT] = SysPortComRequest;
    syscalls[SYS_LOGIN] = SysLogin;
    syscalls[SYS_LOGOUT] = SysLogout;
    syscalls[SYS_USERNAME] = SysAccountName;
    syscalls[SYS_USERREGISTER] = SysRegister;
    syscalls[SYS_USERUNREGISTER] = SysUnRegister;
    syscalls[SYS_USERVERITFY] = SysAccountVerify;
    syscalls[SYS_USERCHPWD] = SysAccountChPwd;
    syscalls[SYS_GROUPCREATE] = SysCreateGroup;
    syscalls[SYS_GROUPREMOVE] = SysRemoveGroup;
    syscalls[SYS_GROUPADDUSER] = SysGroupAddUser;
    syscalls[SYS_GROUPDELUSER] = SysGroupDelUser;
    syscalls[SYS_EXCBLOCK] = SysExceptionBlock;
    syscalls[SYS_EXCCATCH] = SysExceptionCatch;
    syscalls[SYS_EXCHANDLER] = SysExceptionHandler;
    syscalls[SYS_EXCMASK] = SysExceptionMask;
    syscalls[SYS_EXCSEND] = SysExceptionSend;
    syscalls[SYS_MKFIFO] = SysMkFifo;
    syscalls[SYS_MSTATUS] = SysMstatus;
    syscalls[SYS_GETFIREWORK] = SysGetFireworkTable;
    syscalls[SYS_GETVER] = SysGetVer;
    syscalls[SYS_PROBEDEV] = SysProbeDev;
    syscalls[SYS_GETENV] = SysEnvGet;
    syscalls[SYS_SETENV] = SysEnvSet;
    syscalls[SYS_UNSETENV] = SysEnvUnset;
    syscalls[SYS_CLEARENV] = SysEnvClear;
    syscalls[SYS_PUSHENV] = SysEnvPush;
    syscalls[SYS_ENV] = SysEnv;
    syscalls[SYS_GETDISK] = SysDiskInfoGet;
    syscalls[SYS_GETUID] = SysGetUID;
    syscalls[SYS_GETGID] = SysGetGID;
    syscalls[SYS_SCHED_YIELD]=SysTaskYield;
    syscalls[SYS_MOUNTINFO]=SysMountInfo;
#if ENABLE_SWAP
    syscalls[SYS_SWAPMEM] = SysSwapMem;
#endif
}

void SysCallDefault()
{
    KPrint(PRINT_ERR "User call a not support syscall!\n");
    ExceptionRaise(EXC_CODE_SYS);
}

int SysCallCheck(uint32_t call)
{
    if (call > SYSCALL_MAX || call < 0)
    {
        KPrint("syscall: bad syscall num=%d\n", call);
        ExceptionRaise(EXC_CODE_SYS);
        return 1;
    }
    return 0;
}

uint64_t SysCallDispatch(trap_frame_t *frame)
{
    task_t *cur = cur_task;
    syscall_fun_t fun;
    uint64_t ret;
    clock_t ticks;

    // start
    ticks = SysGetTicks();
    fun = syscalls[frame->eax];
    ret = fun(frame->ebx, frame->ecx,frame->edx, frame->esi, frame->edi,frame);
    // end
    cur->syscall_ticks_delta = ticks - SysGetTicks();
    cur->syscall_ticks += cur->syscall_ticks_delta;
    return ret;
}
